import { ChildProcess, spawn, exec } from 'child_process';
import path from 'path';

export class GrpcProxy {
    private static instance: GrpcProxy;
    process: ChildProcess = null!;

    public static getInstance(): GrpcProxy {
        if (!GrpcProxy.instance) {
            GrpcProxy.instance = new GrpcProxy();
        }
        return GrpcProxy.instance;
    }

    constructor() { }

    public getFilePath() {
        return '/extensions/mlagents/bin/mac/grpcwebproxy';
    }

    public async start() {
        const connectTrainer = await Editor.Profile.getProject('mlagents', 'connectTrainer');
        if (!connectTrainer) {
            return;
        }

        const filePath = this.getFilePath();
        const fileAbsPath = path.join(Editor.Project.path, filePath);

        const showLog = await Editor.Profile.getProject('mlagents', 'showProxyLog');
        const editorTrainingPort = await Editor.Profile.getProject('mlagents', 'editorTrainingPort');
        const editorProxyPort = await Editor.Profile.getProject('mlagents', 'editorProxyPort');

        // const certFile = path.join(Editor.Project.path, '/extensions/mlagents/misc/localhost.crt');
        // const keyFile = path.join(Editor.Project.path, '/extensions/mlagents/misc/localhost.key');
        const options = [
            `--backend_addr=localhost:${editorTrainingPort}`,
            `--server_http_debug_port=${editorProxyPort}`,
            '--run_tls_server=false',
            '--allow_all_origins=true'
        ]

        console.log(`[mlagent] start: proxy ${editorProxyPort} -> trainer ${editorTrainingPort}`);

        this.process = spawn(fileAbsPath, options, {
            detached: true,
        });

        this.process?.stdout?.on('data', (data) => {
            if (showLog) {
                console.info(`[mlagent] ${data}`);
            }

        });

        this.process?.stderr?.on('data', (data) => {
            console.error(`[mlagent] error: ${data}`);
        });

        this.process.on('close', (code) => {
            console.info(`child process exited with code ${code}`);
        });
    }

    public stop() {
        if (this.process) {
            this.process.kill('SIGTERM');
        } else {
            this.kill();
        }
    }

    kill() {
        const processName = 'grpcwebproxy';
        // 查找进程
        exec(`pgrep -f ${processName}`, (error, stdout, stderr) => {
            if (error || stderr) {
                console.info(`没有找到匹配名称为"${processName}"的进程或发生错误`);
                return;
            }
            if (stdout) {
                console.info(`找到匹配名称为"${processName}"的进程，进程ID为:\n${stdout}`);
                // 杀死进程
                exec(`pkill -f ${processName}`, (killError, killStdout, killStderr) => {
                    if (killError || killStderr) {
                        console.info(`尝试关闭进程时发生错误`);
                        return;
                    }
                    console.info(`进程"${processName}"已被关闭`);
                });
            } else {
                console.info(`没有找到匹配名称为"${processName}"的进程`);
            }
        });

    }
}
